<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
<script>
    function* foo(x) {
        var y = 2 * (yield (x + 1));
        var z = yield (y / 3);
        return (x + y + z);
    }

    var a = foo(5);
    a.next() // Object{value:6, done:false}
    a.next() // Object{value:NaN, done:false}
    a.next() // Object{value:NaN, done:true}

    var b = foo(5);
    b.next() // { value:6, done:false }
    b.next(12) // { value:8, done:false }
    b.next(13) // { value:42, done:true }

    // 第二次运行next方法时不带参数 导致y的值为2 * undefined (NaN) 除以3以后还是NaN 因此返回对象的value属性也等于NaN
    // 第三次运行next方法的时候不带参数 所以z等于undefined 返回对象的 value 属性等于 5 + NaN + undefined (NaN)

    // 如果next方法提供参数 返回结果就完全不一样 
    // 第一次调用b的next方法 x+1 = 6 
    // 第二次调用next方法 将上一次yield表达式的值设为12 因此y = 24 返回y/3的值8
    // 第三次调用next方法 将上一次yield表达式的值设为13 因此z = 13 这时x = 5 y = 24 所以return 42

    // 注意
    // 由于next方法的参数表示上一个yield表达式的返回值 所以在第一次使用next方法时 传参数是无效的 
    // 只有从第二次使用next方法开始 参数才是有效的 
    // 从语义上讲
    // 第一个next方法用来启动遍历器所以不用带有参数


    function* dataConsumer() {
        console.log('Started');      // Started
        console.log(`1. ${yield}`);  // 1. a
        console.log(`2. ${yield}`);  // 2. b
        return 'result';
    }

    let genObj = dataConsumer();
    console.log(genObj.next()); // {value: undefined, done: false}
    console.log(genObj.next('a')); // {value: undefined, done: false}
    console.log(genObj.next('b')); // {value: "result", done: true}
    console.log(genObj.next('c')); // {value: undefined, done: true}

    


</script>